<?php

class Moip {
    private $credential;
    private $reason;
    private $uniqID;
    private $environment;
    private $uniqueID;
    private $payment_ways = array(
        'billet' => 'BoletoBancario',
        'financing' => 'FinanciamentoBancario',
        'debit' => 'DebitoBancario',
        'creditCard' => 'CartaoCredito',
        'debitCard' => 'CartaoDebito'
    );
    private $institution = array (
            'moip' => 'MoIP',
            'visa' => 'Visa',
            'american_express' => 'AmericaExpress',
            'mastercard' => 'Mastercard',
            'diners' => 'Diners',
            'banco_brasil' => 'BancoDoBrasil',
            'bradesco' => 'Bradesco',
            'itau' => 'Itau',
            'real' => 'BancoReal',
            'unibanco' => 'Unibanco',
            'aura' => 'Aura',
            'hipercard' => 'Hipercard',
            'paggo' => 'Paggo',
            'banrisul' => 'Banrisul'
    );    
    private $payment_method;    
    private $payment_method_args;
    private $payment_type;
    private $payer;
    private $answer;
    private $value;
    private $xml;
    private $errors;    

    public function __construct()
    {
        $this->setEnviroment();
         
        if(!$this->payment_type)
        {
            $this->payment_type = 'Basic';
        }
        
        $this->initXMLObject();
    }
     
    private function initXMLObject()
    {
        $this->xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><EnviarInstrucao></EnviarInstrucao>');
        $this->xml->addChild('InstrucaoUnica');
    }
     
    public function setPaymentType($tipo)
    {
        if($tipo == 'Basic' || $tipo == 'Identification')
        {
            $this->payment_type = $tipo;
        }
        else
        {
            $this->setError("Error: The variable type must contain values 'Basic' or 'Identification'");
        }
         
        return $this;
    }
     
    public function setCredential($credential)
    {
        if(!isset($credential['token']) || !isset($credential['key'])
                || strlen($credential['token']) != 32 || strlen($credential['key']) != 40)
            $this->setError("Error: credential invalid");
         
        $this->credential = $credential;
        return $this;
    }
     
    public function setEnviroment($environment = null)
    {
        if($environment == 'test')
        {
            $return = (object)array();
            $return->name = "Sandbox";
            $return->base_url = "https://desenvolvedor.moip.com.br/sandbox";
        }
        else
        {
            $return = (object)array();
            $return->name = "Producao";
            $return->base_url = "https://www.moip.com.br";
        }
         
        $this->environment = $return;
         
        return $this;
    }
     
    public function validate($validateType = "Basic")
    {
        $this->setPaymentType($validateType);
         
        if(!isset($this->credential) or !isset($this->reason) or !isset($this->uniqueID))
            $this->setError("[setCredential], [setReason] and [setUniqueID] are required");
         
        $payer = $this->payer;
         
        if($this->payment_type == 'Identification')
        {
            $dataValidate = array(
                    'name',
                    'email',
                    'payerId',
                    'billingAddress',
            );
             
            $dataValidateAddress = array(
                    'address',
                    'number',
                    'complement',
                    'neighborhood',
                    'city',
                    'state',
                    'country',
                    'zipCode',
                    'phone'
            );
             
            foreach($dataValidate as $key)
            {
                if(!isset($payer[$key]))
                {
                    $notSeted = $key;
                    $varNotSeted.= ' ['.$key.'] ';
                }
            }
             
            foreach($dataValidateAddress as $key)
            {
                if(!isset($payer['billingAddress'][$key]))
                {
                    $notSeted = $key;
                    $varNotSeted.= ' ['.$key.'] ';
                }
            }            
            
             
            if($notSeted || $notValid)
                $this->setError('Error: The following data required were not informed: '.$varNotSeted.'.');
        }
         
        return $this;
    }
     
    public function setUniqueID($id)
    {
        $this->uniqueID = $id;
        return $this;
    }
     
    public function setReason($reason)
    {
        $this->reason = $reason;
        return $this;
    }
     
    public function addPaymentWay($way)
    {
        if(!isset($this->payment_ways[$way]))
            $this->setError("Error: Payment method unavailable");
        else
            $this->payment_way[] = $way;
         
        return $this;
    }
    
    public function setValue($value)
    {
        $this->value = $value;
        return $this;
    }
     
    public function setPayer($payer)
    {
        $this->payer = $payer;
        return $this;
    }
     
    public function setAdds($value)
    {
        $this->adds = $value;
        return $this;
    }
     
    public function setDeduct($value)
    {
        $this->deduction = $value;
        return $this;
    }
     
    public function addMessage($msg)
    {
        if(!isset($this->xml->InstrucaoUnica->Mensagens))
        {
            $this->xml->InstrucaoUnica->addChild('Mensagens');
        }
         
        $this->xml->InstrucaoUnica->Mensagens->addChild('Mensagem', $msq);
        return $this;
    }
     
    public function setReturnURL($url)
    {
        if(!isset($this->xml->InstrucaoUnica->URLRetoro))
        {
            $this->xml->InstrucaoUnica->addChild('URLRetorno', $url);
        }
    }
     
    public function setNotificationURL($url)
    {
        if(!isset($this->xml->InstrucaoUnica->URLNotificacao))
        {
            $this->xml->InstrucaoUnica->addChild('URLNotificacao', $url);
        }
    }
     
    public function setError($error)
    {
        $this->errors = $error;
        return $this;
    }
     
    public function getXML()
    {
        if($this->payment_type == "Identification")
            $this->xml->InstrucaoUnica->addAttribute('TipoValidacao', 'Transparent');
         
        $this->xml->InstrucaoUnica->addChild('IdProprio', $this->uniqueID);
        $this->xml->InstrucaoUnica->addChild('Razao', $this->reason);
         
        if(empty($this->value))
            $this->setError('Error: The transaction amount must be specified.');
         
        $this->xml->InstrucaoUnica->addChild('Valores');
        $this->xml->InstrucaoUnica->Valores->addChild('Valor', "$this->value")->addAttribute('moeda', 'BRL');
         
        if(isset($this->deducation))
        {
            $this->xml->InstrucaoUnica->Valores->addChild('Deducao', $this->deduction)
            ->addAttribute('moeda', 'BRL');
        }
         
        if(isset($this->adds))
        {
            $this->xml->InstrucaoUnica->Valores->addChild('Acrescimo', $this->adds)
            ->setAttribute('moeda', 'BRL');
        }
         
        if(!empty($this->payment_way))
        {
            $instrucao = $this->xml->InstrucaoUnica;
            $formas = $instrucao->addChild('FormasPagamento');
             
            foreach($this->payment_way as $way)
            {
                $formas->addChild('FormaPagamento', $this->payment_ways[$way]);
            }
        }
         
        if(!empty($this->payer))
        {
            $p = $this->payer;
            $this->xml->InstrucaoUnica->addChild('Pagador');
            (isset($p['name'])) ? $this->xml->InstrucaoUnica->Pagador->addChild('Nome', $this->payer['name']) : null;
            (isset($p['email'])) ? $this->xml->InstrucaoUnica->Pagador->addChild('Email', $this->payer['email']) : null;
            (isset($p['payerId'])) ? $this->xml->InstrucaoUnica->Pagador->addChild('IdPagador', $this->payer['payerId']) : null;
            (isset($p['identity'])) ? $this->xml->InstrucaoUnica->Pagador->addChild('Identidade', $this->payer['identity']) : null;
            (isset($p['phone'])) ? $this->xml->InsctrucaoUnica->Pagador->addChild('TelefoneCelular', $this->payer['phone']) : null;
             
            $p = $this->payer['billingAddress'];
            $this->xml->InstrucaoUnica->Pagador->addChild('EnderecoCobranca');
            (isset($p['address'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Logradouro', $this->payer['billingAddress']['address']) : null;
            (isset($p['number'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Numero', $this->payer['billingAddress']['number']) : null;

            (isset($p['complement'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Complemento', $this->payer['billingAddress']['complement']) : null;
            (isset($p['neighborhood'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Bairro', $this->payer['billingAddress']['neighborhood']) : null;
            (isset($p['city'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Cidade', $this->payer['billingAddress']['city']) : null;
            (isset($p['state'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Estado', $this->payer['billingAddress']['state']) : null;
            (isset($p['country'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('Pais', $this->payer['billingAddress']['country']) : null;
            (isset($p['zipCode'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('CEP', $this->payer['billingAddress']['zipCode']) : null;
            (isset($p['phone'])) ? $this->xml->InstrucaoUnica->Pagador->EnderecoCobranca->addChild('TelefoneFixo', $this->payer['billingAddress']['phone']) : null;
        }
         
        $return = utf8_encode($this->xml->asXML());
        $this->initXMLObject();
        return str_ireplace("\n", "", $return);
    }
     
     
    public function send($client=null)
    {
        $this->validate();
         
        if($client == null)
            $client = new MoipClient();
         
        $url = $this->environment->base_url.'/ws/alpha/EnviarInstrucao/Unica';
         
        return $this->answer = $client->curlPost($this->credential['token'].':'.$this->credential['key'],
                $this->getXML(),
                $url, $this->errors);
    }
     
    public function getAnswer($formato=null)
    {
        if($this->answer->response == true)
        {
            if($formato == "xml")
            {
                return $this->answer->xml;
            }
             
            $xml = new SimpleXmlElement($this->answer->xml);
             
            $return = (object) array();
            $return->response = $xml->Resposta->Status == 'Sucesso' ? true : false;
            $return->error = $xml->Resposta->Status == 'Falha' ? (string) utf8_decode($xml->Resposta->Erro) : false;
            $return->token = (string)$xml->Resposta->Token;
            $return->payment_url = $xml->Resposta->Status == 'Sucesso' ? (string)$this->environment->base_url."/Instrucao.do?token=".$return->token : false;
             
            return $return;
        }
        else
        {
            return $this->answer->error;
        }
    }
}